home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / doc.lha / documentation / manual / control.mss < prev    next >
Text File  |  1987-06-30  |  18KB  |  494 lines

  1. @part[CONTROL, Root "TMAN.MSS"]         @Comment{-*-System:TMAN-*-}
  2. @chap[Control]
  3.  
  4. @dc{ Talk about calls, tail-recursion, conditionals, etc. }
  5.  
  6. @section [Conditionals]
  7. @label[ConditionalsSection]     @Comment{ref: objects chapter}
  8. @index[Conditionals]
  9.  
  10. @info[NOTES="Special form"]
  11. @desc[@el[](COND . @i[clauses]) @yl[] @i[value-of-clause]]
  12. @tc[COND] is a general conditional construct.  Each @i[clause] should
  13. have one of the following forms:
  14. @begin[tc]
  15. @begin[itemize]
  16. (@i[test] . @i[body])
  17.  
  18. (@i[test])
  19.  
  20. (@i[test] => @i[procedure])
  21.  
  22. @end[Itemize]
  23. @end[tc]
  24. The @i[test] expressions are evaluated in sequence until one yields true,
  25. at which point:
  26. @Itemize[
  27. If it is part of a clause of the form @wt[(@i[test] . @i[body])],
  28. then @i[body], an implicit block, is evaluated, and its value is what
  29. the @tc[COND]-expression yields.
  30.  
  31. If the clause has the form @wt[(@i[test])], then the @tc[COND]-expression yields
  32. the value of @i[test] (which of course is non-null).
  33.  
  34. If the clause has the form
  35. @wt[(@i[test] => @i[procedure])], then the @i[procedure]
  36. expression is evaluated, and its value, which should be
  37. a procedure, is called with the value of the @i[test] as its one and only
  38. argument.  The @tc[COND] yields the value of that call.
  39. ]
  40.  
  41. Example:
  42.   @begin[TEG]
  43. (COND ((PAIR? X)   (GAUR (CAR X)))
  44.       ((FIXNUM? X) (GAUR X)))
  45.   @end[TEG]
  46.  
  47. If all the @i[tests] yield false, then the @tc[COND] yields an
  48. undefined value.
  49. See section @ref[undefined semantics section] for a discussion of undefined
  50. values.
  51.  
  52. The system variable @tix[ELSE] has a non-null value.  This provides a
  53. convenient way to specify a branch to take when all other @i[tests]
  54. fail.
  55.  
  56.   @begin[TEG]
  57. (COND ((PAIR? X) (GAUR (CAR X)))
  58.       ((ASSQ X *SAMPLE-ALIST*) => CDR)
  59.       ((GAUR X))
  60.       (ELSE NIL))
  61.   @end[TEG]
  62. @dc{ Important: devise examples which illustrate all the various
  63. features of @tc[COND]. }
  64.  
  65. @EndDesc[COND]
  66.  
  67. @info[NOTES="Special form"]
  68. @desc[(XCOND . @i[clauses]) @yl[] @i[value-of-clause]]
  69. Similar to @tc[COND], but its effect is undefined (and presumably an error
  70. is signalled) if no @i[clause] is selected.  @tc[X] is mnemonic for
  71. @qu"exhaustive".
  72. @enddesc[XCOND]
  73.  
  74. @desc[@el[]ELSE @yl[] @i[true]]
  75. @tc[ELSE] has as its value some true value.
  76. It exists mainly for use in @tc[COND].
  77. @EndDesc[ELSE]
  78.  
  79. @info[NOTES="Special form"]
  80. @descN[
  81. F1="@el[](IF @i[test consequent alternate]) @yl[] @i[value-of-arm]", FN1="IF",
  82. F2="@el[](IF @i[test consequent]) @yl[] @i[undefined]"
  83. ]
  84. @tc[IF] is a primitive two-way conditional.  The @i[test] expression
  85. is evaluated.  If it yields true, then the @i[consequent] expression is
  86. evaluated, and the @tc[IF] yields its value.  Otherwise, the
  87. @i[alternate] expression, if any, is evaluated, and the @tc[IF] yields its
  88. value.  If @i[test] yields false and there is no @i[alternate],
  89. then the value of the @tc[IF] is undefined.
  90.   @begin[ProgramExample]
  91. (IF T 1 2)                 @ev[]  1
  92. (IF (PAIR? 'X) 'FOO 'BAR)  @ev[]  BAR
  93.  
  94. (IF @i[test] @i[consequent])  @ce[]  (IF @i[test] @i[consequent] (UNDEFINED-VALUE))
  95.   @end[ProgramExample]
  96. @EndDescN[IF]
  97.  
  98. @AnEquivE[Tfn="CASE",Efn="SELECTQ"]
  99. @info[NOTES="Special form",EQUIV="CASEQ"]
  100. @desc[(CASE @i[key] . @i[clauses]) @yl[] @i[value-of-clause]]
  101.  
  102. @tc[CASE] performs a multi-way dispatch based on the value of the
  103. @i[key] expression.  Each @i[clause] should be of the form
  104. @wt[(@i[keys] . @i[body])], where @i[keys] is a list of values (@i[not]
  105. expressions!) against which the value of the @i[key] expression is
  106. compared (using @tc[EQ?]), and @i[body] is an implicit block.  The
  107. body of the clause which matches the @i[key] value is evaluated, and
  108. the @tc[CASE]-expression yields the value of the body.  The last
  109. @i[clause] may be of the form @wt[(ELSE . @i[body])]; this designates
  110. a default action to be taken if no other clause is selected.  If the
  111. @i[key] never matches and there is no default clause, then the
  112. @tc[CASE]-expression yields an undefined value.
  113.   @begin[ProgramExample]
  114. (CASE 'B ((A) 'LOSE) ((B C) 'WIN) (ELSE NIL))  @ev[]  WIN
  115.   @end[ProgramExample]
  116. @EndDesc[CASE]
  117.  
  118. @info[NOTES="Special form"]
  119. @desc[(XCASE @i[key] . @i[clauses]) @yl[] @i[value-of-clause]]
  120. Similar to @tc[CASE], but no @tc[ELSE]-clause is permitted, and
  121. the effect is undefined (and presumably an error is signalled)
  122. if no @i[clause] is selected.
  123. @EndDesc[XCASE]
  124.  
  125. @info[NOTES="Special form"]
  126. @desc[(SELECT @i[key] . @i[clauses]) @yl[] @i[value-of-clause]]
  127. @tc[SELECT] is like @tc[CASE], but the car of each @i[clause] is a list
  128. of expressions that are evaluated, instead of a list of constants.
  129. @begin[ProgramExample]
  130. (DEFINE *RED-COLOR*   ...)
  131. (DEFINE *GREEN-COLOR* ...)
  132. (DEFINE *BLUE-COLOR*  ...)
  133. (SELECT COLOR
  134.         ((*RED-COLOR* *BLUE-COLOR*) 'INORGANIC)
  135.         ((*GREEN-COLOR*)            'ORGANIC))
  136. @end[ProgramExample]
  137. @EndDesc[SELECT]
  138.  
  139. @info[NOTES="Special form"]
  140. @desc[(XSELECT @i[key] . @i[clauses]) @yl[] @i[value-of-clause]]
  141. Similar to @tc[SELECT], but no @tc[ELSE]-clause is permitted, and
  142. the effect is undefined (and presumably an error is signalled)
  143. if no @i[clause] is selected.
  144. @EndDesc[XSELECT]
  145.  
  146. @info[NOTES="Type predicate"]
  147. @descN[
  148. F1="(NOT @i[object]) @yl[] @i[boolean]", FN1="NOT",
  149. F2="(FALSE? @i[object]) @yl[] @i[boolean]", FN2="FALSE?"
  150. ]
  151. @tc[NOT] returns true if @i[object] is false, and returns false otherwise.
  152. @begin[ProgramExample]
  153. (NOT NIL)  @ev[]  @r[true]
  154. (NOT T)    @ev[]  @r[false]
  155. (NOT 3)    @ev[]  @r[false]
  156. @end[ProgramExample]
  157. @EndDescN[]
  158.  
  159. @info[NOTES="Special form"]
  160. @desc[@el[](AND . @i[tests]) @yl[] @i[value-of-test] @r[or] @i[false]]
  161. The @i[test] expressions are evaluated from left to right, until one
  162. evaluates to false, at which point the @tc[AND] yields false.
  163. If no @i[test] evaluates to false then the value of the @tc[AND]
  164. is the value of the last @i[test].
  165. @begin[ProgramExample]
  166. (AND 3 4)    @ev[]  4
  167. (AND 3 NIL)  @ev[]  @r[false]
  168. (AND)        @ev[]  @r[true]
  169. @end[ProgramExample]
  170. @EndDesc[AND]
  171.  
  172. @info[NOTES="Special form"]
  173. @desc[@el[](OR . @i[tests]) @yl[] @i[value-of-test] @i[or] @i[false]]
  174. The @i[test] expressions are evaluated from left to right, until one
  175. evaluates to true (i.e., not null); its value is yielded as the value
  176. of the @tc[OR].  If no @i[test] evaluates to true, then the value
  177. of the @tc[OR] is false.
  178. @begin[ProgramExample]
  179. (OR 3 4)    @ev[]  3
  180. (OR 3 NIL)  @ev[]  3
  181. (OR)        @ev[]  @r[false]
  182. @end[ProgramExample]
  183. @EndDesc[OR]
  184.  
  185. @desc[(*AND . @i[objects]) @yl[] @i[object]]
  186. If any of the @i[objects] is false, @tc[*AND] returns false; otherwise
  187. it returns the last @i[object].  This is superficially similar to
  188. @tc[AND], but it is a procedure, not a special form.  That is, the
  189. value of @tc[*AND] is a procedure, whereas @tc[AND] is a reserved word
  190. which introduces a special syntactic form.
  191. This fact implies that (a) the variable @tc[*AND] has a value suitable
  192. to be passed as an argument to some procedure, and
  193. (b) a call to @tc[*AND] behaves differently from
  194. an @tc[AND] special form in the case that the argument expressions have
  195. side-effects.  In
  196.   @begin[ProgramExample]
  197. (AND NIL (FOO))
  198.   @end[ProgramExample]
  199. @tc[FOO] will not be called, whereas in
  200.   @begin[ProgramExample]
  201. (*AND NIL (FOO))
  202.   @end[ProgramExample]
  203. @tc[FOO] @i[will] be called.
  204. @EndDesc[*AND]
  205.  
  206. @desc[(*OR . @i[objects]) @yl[] @i[object]]
  207. If any of the @i[objects] is true, @tc[*OR] returns that object; otherwise
  208. it returns false.  @tc[*OR]'s relation to @tc[OR] is
  209. analogous to @tc[*AND]'s relation to @tc[AND].
  210. @EndDesc[*OR]
  211.  
  212. @desc[(*IF @i[test consequent alternate]) @yl[] @i[object]]
  213. If @i[test] is true, @tc[*IF] returns @i[consequent];
  214. otherwise it returns @i[alternate].  @tc[*IF]'s relation to @tc[IF] is
  215. analogous to @tc[*AND]'s relation to @tc[AND].
  216. @EndDesc[*IF]
  217.  
  218.  
  219. @section[Iteration]
  220. @index[Iteration]
  221. @index[Loops]
  222.  
  223. Separate iteration constructs are not strictly necessary in @Tau[],
  224. since iteration may be written using recursive procedures defined
  225. by @tc[LABELS] (or even @tc[DEFINE]).  There is no penalty for this
  226. in @Tau[], either in efficiency or practicality (for example, stack
  227. size), because tail-recursions are implemented without net growth
  228. of stack, and it is expected that compilers will implement local
  229. procedures efficiently.
  230.  
  231. However, the following two iteration constructs provide a somewhat
  232. more convenient notation for loops than does @tc[LABELS].  (There
  233. are also some higher-order procedures which perform iteration; see
  234. for example @tc[MAP], page @pageref[MAP], and @tc[WALK], page
  235. @pageref[WALK].)
  236.  
  237. @info[NOTES="Special form"]
  238. @desc[(DO @i[specs] (@i[end-test] . @i[exit-forms]) . @i[body]) @~
  239.  @yl[] @i[value-of-exit]]
  240. Iterates until @i[end-test] yields true.
  241. Each @i[spec] should be of the form
  242. @wt[(@i[variable initial next])].
  243. The @i[variables] are initialized (bound) in parallel to the values
  244. of the @i[initial]-expressions, as with @tc[LET];
  245. then, the @i[end-test] and @i[body] are executed iteratively.
  246. If the @i[end-test] yields true on any iteration, then the loop
  247. terminates, at which point the @i[exit-forms] are evaluated.
  248. The value of the @tc[DO]-expression is the value of the
  249. last @i[exit-form], or the value of the @i[end-test]
  250. if there are no @i[exit-forms] (this is like a @tc[COND] clause).
  251. At the end of each iteration, the @i[next]-expressions are all evaluated,
  252. and the @i[variables] are re-bound
  253. to the values of the @i[next]-expressions.
  254.  
  255. @tc[DO] is useful for loops which have a single termination condition,
  256. such as numerical, ALGOL-style @tc[for]-loops, loops where desired
  257. results are accumulated in variables, and loops that perform
  258. side-effects on every element in a sequence
  259. (see @tc[WALK], page @PageRef[WALK]).
  260.   @begin[ProgramExample]
  261. (REVERSE L)  @ce[]
  262.   (DO ((L L (CDR L))
  263.        (RESULT '() (CONS (CAR L) RESULT)))
  264.       ((NULL? L) RESULT)))
  265.  
  266. (VECTOR-FILL VECTOR CONSTANT)  @ce[]
  267.   (DO ((I (-1+ (VECTOR-LENGTH VECTOR)) (-1+ I)))
  268.       ((<0? I) VECTOR)
  269.     (VSET VECTOR I CONSTANT))
  270.   @end[ProgramExample]
  271.  
  272. Any @tc[DO]-expression may be rewritten using the more primitive @tc[LABELS]
  273. construct.  The following example has only one induction variable and
  274. one @i[body]-expression, and assumes that there are no name conflicts
  275. with the variable @tc[LOOP].
  276.   @begin[ProgramExample]
  277. (DO ((@i[variable] @i[initial] @i[next])) @i[exit-clause] @i[body])
  278.   @ce[]
  279. (LABELS (((LOOP @i[variable])
  280.           (COND @i[exit-clause]
  281.                 (ELSE @i[body]
  282.                       (LOOP @i[next])))))
  283.   (LOOP @i[initial]))
  284.   @end[ProgramExample]
  285. @EndDesc[DO]
  286.  
  287. @info[NOTES="Special form"]
  288. @desc[(ITERATE @i[variable specs] . @i[body]) @yl[] @i[value-of-body]]
  289. Another iteration construct.
  290. @i[Specs] has the form
  291. @begin[ProgramExample]
  292. ((@i[arg@-[1] val@-[1]]) (@i[arg@-[2] val@-[2]]) ... (@I[arg@-[n] val@-[n]]))
  293. @end[ProgramExample]
  294. The @i[variable] is bound to a local procedure whose formal parameters
  295. are @i[arg@-[1] arg@-[2] ... arg@-[n]].  The procedure is initially invoked
  296. with the @i[val]s bound to the corresponding @i[arg]s.
  297.  
  298. @tc[ITERATE] is more flexible than @tc[DO].  It is useful in loops where
  299. the terminating condition occurs in the middle of the body of the loop,
  300. or where there is more than one terminating condition, or where the
  301. iteration may occur in several places.
  302.  
  303. For example, consider the following example (from @Cite[STEELE78REV]),
  304. a procedure to sort a list of trees into atoms and lists:
  305.   @begin[ProgramExample]
  306. (DEFINE (COLLATE X)
  307.   (ITERATE COL ((Z X) (ATOMS '()) (LISTS '()))
  308.     (COND ((NULL? Z)
  309.            (LIST ATOMS LISTS))
  310.           ((ATOM? (CAR Z))
  311.            (COL (CDR Z) (CONS (CAR Z) ATOMS) LISTS))
  312.           (ELSE
  313.            (COL (CDR Z) ATOMS (CONS (CAR Z) LISTS))))))
  314.   @end[ProgramExample]
  315. A rough analogy @tc[ITERATE : LABELS :: LET : LAMBDA] holds.
  316. @tc[ITERATE] expands trivially into @tc[LABELS], but may be more convenient
  317. than @tc[LABELS] for the same reason that a @tc[LET] form may be preferable
  318. than a call to a @tc[LAMBDA]-expression.
  319.   @begin[ProgramExample]
  320. (ITERATE @i[variable] @~
  321. ((@i[arg@-[1] val@-[1]]) (@i[arg@-[2] val@-[2]]) ... (@i[arg@-[n] val@-[n]])) @~
  322. . @i[body])
  323.   @ce[]
  324. (LABELS (((@i[variable arg@-[1] arg@-[2] ... arg@-[n]]) . @i[body])) @~
  325.   (@i[variable val@-[1] val@-[2] ... val@-[n]]))
  326.   @end[ProgramExample]
  327. @EndDesc[ITERATE]
  328.  
  329.  
  330. @section[Procedure application]
  331.  
  332. The only operation which all procedures support is invocation.
  333. All initial system routines, like @tc[CAR], @tc[LIST], and @tc[EQ?], are
  334. procedures.  Procedures are usually created by evaluating @tc[LAMBDA]-
  335. or @tc[DEFINE]-forms.
  336. @index[procedures]
  337.  
  338. The standard way to apply a procedure to arguments is with a
  339. @i[call] expression.  Calls are described on page @pageref[callsemantics].
  340. @index[calls]
  341.  
  342. @dc{ Describe @tc[CALL], just for fun?  People might not understand
  343. that it's redundant. }
  344.  
  345. @info[NOTES="Type predicate"]
  346. @desc[(PROCEDURE? @i[object]) @yl[] @i[boolean]]
  347. Returns true if @i[object] is a procedure, i.e., if it may be called.
  348. @EndDesc[PROCEDURE?]
  349.  
  350. @desc[(APPLY @i[procedure] . @i[objects]) @yl[] @i[object]]
  351. @tc[APPLY] applies a procedure to a list of arguments.
  352.  
  353. The sequence of @i[object] arguments should have the form
  354. @begin[ProgramExample]
  355. @i[arg@-[1] arg@-[2]] ... @i[arg@-[n] arglist]
  356. @end[ProgramExample]
  357. where @i[n] may be 0.  The @i[procedure] is called with
  358. @i[arg@-[1]], @i[arg@-[2]], etc., as the first @i[n] arguments,
  359. and the members of @i[arglist] as final arguments.
  360. @begin[ProgramExample]
  361. (APPLY CONS '(1 2))          @ev[]  (1 . 2)
  362. (APPLY CONS 1 '(2))          @ev[]  (1 . 2)
  363. (APPLY CONS 1 2 '())         @ev[]  (1 . 2)
  364. (APPLY LIST 1 2 3 '(4 5 6))  @ev[]  (1 2 3 4 5 6)
  365. @end[ProgramExample]
  366. @EndDesc[APPLY]
  367.  
  368.  
  369. @section[Sequencing]
  370.  
  371. @info[NOTES="Special form",EQUIV="PROGN",BRIEF="; Like PROGN"]
  372. @desc[@el[](BLOCK . @i[body]) @yl[] @i[value-of-body]]
  373. @i[Body] is a non-empty sequence of expressions.
  374. These expressions are evaluated in order from left to right.
  375. The @tc[BLOCK]-expression
  376. yields the value of the last expression.
  377.  
  378. Because their values are ignored, expressions other than the last are
  379. useful only for side-effects they may cause.
  380.  
  381. Since the bodies of most special forms are implicitly blocks, @tc[BLOCK]
  382. is useful only in places where syntactically a single expression is
  383. needed, but some sequencing is required.
  384. @EndDesc[BLOCK]
  385.  
  386. @info[NOTES="Special form",EQUIV="PROG1",BRIEF="; Like PROG1"]
  387. @desc[(BLOCK0 @i[first-form] . @i[body]) @yl[] @i[value-of-first-form]]
  388. The @i[first-form] is evaluated, then the expressions in the @i[body]
  389. are evaluated.  The @tc[BLOCK0]-expression yields @i[first-form]'s value.
  390. @EndDesc[BLOCK0]
  391.  
  392.  
  393. @section[Non-local exits]
  394.  
  395. @AnEquivE[Tfn="CATCH",Efn="RETURN"]
  396. @AnEquivE[Tfn="CATCH",Efn="CATCH"]
  397. @AnEquivE[Tfn="CATCH",Efn="THROW"]
  398. @AnEquivE[Tfn="CATCH",Efn="*CATCH"]
  399. @AnEquivE[Tfn="CATCH",Efn="*THROW"]
  400. @info[NOTES="Special form"]
  401. @desc[(CATCH @i[variable] . @i[body]) @yl[] @i[value-of-body]]
  402. @tc[CATCH] provides a structured, non-local exit facility
  403. similar to @tc[PROG] and @tc[RETURN] (without @tc[GO]),
  404. or @tc[CATCH] and @tc[THROW], in other Lisps.
  405. The @i[variable] is bound to an @i[escape procedure]
  406. of one argument.  If the escape procedure is called
  407. as a result of evaluating @i[body], then the argument to the
  408. @i[escape procedure]
  409. is returned as the value of the @tc[CATCH]-expression.
  410. If the escape procedure is not called, then @tc[CATCH] returns whatever
  411. @i[body] returns.
  412. A call to an escape procedure is called a @i[throw].@index[throws]
  413.  
  414. In the following example, the call to @tc[LIST] never happens,
  415. because one of its subforms performs a throw.
  416. @begin[ProgramExample]
  417. (CATCH X (LIST 1 (X 2) 3))  @ev[]  2
  418. @end[ProgramExample]
  419. @tau[]'s @tc[CATCH] is a restriction of SCHEME's.
  420. Escape procedures are only valid within the dynamic extent of the
  421. @tc[CATCH]-expression; the @tc[CATCH] can yield a value at most once.
  422. Escape procedures should not be returned @qu"upwards."
  423.  
  424. A throw may cause side-effects if the dynamic state in effect when the
  425. escape procedure is called differs from that in effect when evaluation
  426. of its corresponding @tc[CATCH]-expression began.@index[dynamic state]
  427. In this case the
  428. throw undoes the effects of @tc[BIND] forms, and must perform cleanup
  429. action requested by @tc[UNWIND-PROTECT] forms, in the process of
  430. @qu"unwinding" the evaluation context from that of the throw to that of
  431. the @tc[CATCH].  See section @ref[dynamic state section] for
  432. descriptions of @tc[BIND] and @tc[UNWIND-PROTECT].
  433. @EndDesc[CATCH]
  434.  
  435.  
  436. @section[Lazy evaluation]
  437.  
  438. @iix[Delays] provide a general mechanism for delayed (lazy) evaluation,
  439. also known as @qu"call-by-need".
  440. @index[Lazy evaluation]
  441. @index[Call-by-need]
  442.  
  443. @dc{ Where does this belong, really? }
  444.  
  445. @dc{ Should we admit that this is just a trivial macro in terms of
  446. @tc[LAMBDA]? }
  447.  
  448. @info[NOTES="Special form"]
  449. @desc[(DELAY @i[expression]) @yl[] @i[delay]]
  450. Returns a delay of the @i[expression].  The computation of the expression,
  451. which happens at most once, is delayed until its value is
  452. requested with @tc[FORCE].
  453.   @begin[ProgramExample]
  454. (DEFINE (INF-LIST-OF-INTEGERS N)
  455.   (CONS N (DELAY (INF-LIST-OF-INTEGERS (1+ N)))))
  456. (HEAD (TAIL (TAIL (INF-LIST-OF-INTEGERS 1))))  =>  3
  457.  
  458. (DEFINE HEAD CAR)
  459. (DEFINE (TAIL OBJ) (FORCE (CDR OBJ)))
  460.   @end[ProgramExample]
  461. The behavior of @tc[DELAY] and @tc[FORCE] can be described by the
  462. following hypothetical implementation:
  463.   @begin[ProgramExample]
  464. (DEFINE-SYNTAX (DELAY EXP)
  465.   `(MAKE-DELAYED-OBJECT (LAMBDA () ,EXP)))
  466.  
  467. (DEFINE (MAKE-DELAYED-OBJECT THUNK)
  468.   (LET ((FORCED-YET? NIL)
  469.         (FORCED-VALUE NIL))
  470.     (OBJECT NIL
  471.             ((FORCE SELF)
  472.              (COND ((NOT FORCED-YET?)
  473.                     (SET FORCED-VALUE (THUNK))
  474.                     (SET FORCED-YET? T)))
  475.              FORCED-VALUE))))
  476.  
  477. (DEFINE-OPERATION (FORCE OBJ)
  478.   OBJ)
  479.   @end[ProgramExample]
  480. @EndDesc[DELAY]
  481.  
  482. @Desc[(FORCE @i[delay]) @yl[] @i[object]]
  483. Forces the computation of the @i[delay]'s value.
  484. If @t[FORCE] has not previously been applied to the delay,
  485. then the @i[expression] in the original @tc[DELAY]-expression
  486. which created @i[delay] (see above)
  487. is evaluated, and its value is returned.
  488. If @t[FORCE] has previously been applied to the delay,
  489. then the value previously computed is returned.
  490.  
  491. If @tc[FORCE] is applied to a non-delay, then it simply returns
  492. its argument.
  493. @EndDesc[FORCE]
  494.